package com.star.common.protocol.contract.dto;

import com.star.common.core.context.ThreadContext;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;
import java.util.SortedMap;

/**
 * 请求头参数
 *
 * @author zhouhengzhe
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Slf4j
public class HeaderDTO {

    /**
     * 版本号 1.0
     */
    private String version;

    /**
     * 应用ID
     */
    private String tenantId;

    /**
     * 验签值
     */
    private String sign;

    /**
     * 随机数
     */
    private String nonce;

    /**
     * 时间戳
     */
    private Long timestamp;

    /**
     * 语言   GB：英文，zh-CN：简体中文，zh-TW：繁体中文，th-TH：泰语，vi-VN：越南语，id-ID：印尼语"
     */
    private String languageCode;

    /**
     * 请求ID
     */
    private String requestId;

    private static final String VERSION_REGEX = "^\\d+(\\.\\d+)*$";

    public static HeaderDTO parseForRequestHeader(HttpServletRequest servletRequest) {
        HeaderDTO headerDTO = new HeaderDTO();
        String version = servletRequest.getHeader("version");
        if (StringUtils.isNotBlank(version)) {
            headerDTO.version = version.trim();
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("tenantId"))) {
            headerDTO.tenantId = servletRequest.getHeader("tenantId");
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("sign"))) {
            headerDTO.sign = servletRequest.getHeader("sign").trim();
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("nonce"))) {
            headerDTO.nonce = servletRequest.getHeader("nonce").trim();
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("timestamp"))) {
            headerDTO.timestamp = Long.parseLong(servletRequest.getHeader("timestamp").trim());
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("languageCode"))) {
            headerDTO.languageCode = servletRequest.getHeader("languageCode").trim();
        }
        if (StringUtils.isNotBlank(servletRequest.getHeader("requestId"))) {
            headerDTO.requestId = servletRequest.getHeader("requestId").trim();
        }
        return headerDTO;
    }

    public static Boolean validateHeader(HeaderDTO headerDTO) {
        //版本不能为空
        if (StringUtils.isBlank(headerDTO.version)) {
            log.error("version is null");
            return false;
        }
        if (StringUtils.isBlank(headerDTO.tenantId)) {
            log.error("tenantId is null");
            return false;
        }
        //版本号格式校验
        if (!validateVersion(headerDTO.version)) {
            log.error("version format error");
            return false;
        }
        if (StringUtils.isBlank(headerDTO.languageCode)) {
            log.error("languageCode is null");
            return false;
        }
        //签名不能为空
        if (StringUtils.isBlank(headerDTO.sign)) {
            log.error("sign is null");
            return false;
        }
        //随机数不能为空
        if (StringUtils.isBlank(headerDTO.nonce)) {
            log.error("nonce is null");
            return false;
        }
        //时间戳不能为空
        if (Objects.isNull(headerDTO.timestamp)) {
            log.error("timestamp is null");
            return false;
        }
        //限制为（含）60秒以内发送的请求
        if (limitMinuteRequest(headerDTO)) {
            return false;
        }
        //请求ID不能为空
        if (StringUtils.isBlank(headerDTO.requestId)) {
            log.error("requestId is null");
            return false;
        }
        return true;
    }

    /**
     * 限制为（含）60秒以内发送的请求
     *
     * @param headerDTO 请求头参数
     * @return true 限制通过
     */
    private static boolean limitMinuteRequest(HeaderDTO headerDTO) {
        long time = 60;
        long now = System.currentTimeMillis() / 1000;
        if (now - headerDTO.timestamp > time) {
            log.error("timestamp is out of date");
            return true;
        }
        return false;
    }

    /**
     * 把请求头填充排序Map中
     *
     * @param sortedMap 排序Map
     * @param headerDTO 请求头参数
     * @return 排序Map
     */
    public static SortedMap<String, String> fillSortMapFromHeader(SortedMap<String, String> sortedMap, HeaderDTO headerDTO) {
        if (StringUtils.isNotBlank(headerDTO.version)) {
            sortedMap.put("version", headerDTO.version);
        }
        if (StringUtils.isNotBlank(headerDTO.tenantId)) {
            sortedMap.put("tenant_id", headerDTO.tenantId);
        }

        //随机数不能为空
        if (StringUtils.isNotBlank(headerDTO.nonce)) {
            sortedMap.put("nonce", headerDTO.nonce);
        }
        //时间戳不能为空
        if (Objects.nonNull(headerDTO.timestamp)) {
            sortedMap.put("timestamp", headerDTO.timestamp.toString());
        }
        //请求ID不能为空
        if (StringUtils.isNotBlank(headerDTO.languageCode)) {
            sortedMap.put("language_code", headerDTO.languageCode);
        }
        if (StringUtils.isNotBlank(headerDTO.requestId)) {
            sortedMap.put("request_id", headerDTO.requestId);
        }
        return sortedMap;
    }

    /**
     * 校验版本号格式
     *
     * @param version 版本号
     * @return true 校验通过
     */
    private static Boolean validateVersion(String version) {
        // 正则表达式匹配版本号，例如 1.0、1.0.0 或 1.0.0.0
        return version.matches(VERSION_REGEX);
    }

    /**
     * 设置请求头
     *
     * @param headerDTO 请求头参数
     */
    public static void setHeaderContext(HeaderDTO headerDTO) {
        ThreadContext.set("headerDTO", headerDTO);
    }

    /**
     * 清除请求头
     */
    public static void clearHeaderContext() {
        ThreadContext.remove("headerDTO");
    }

    /**
     * 获取请求头
     *
     * @return
     */
    public static HeaderDTO getHeaderContext() {
        return ThreadContext.get("headerDTO");
    }
}
